
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package recocido;
import grasp1.Empleado;
import grasp1.Galleta;
import grasp1.Grasp;
import grasp1.Solucion;
import grasp1.TipoGalleta;
import java.util.ArrayList;
import java.util.Random;
/**
 *
 * @author WALTER
 */
public class Recocido {
    
     private double tInicial = 100;
    private double tMinima = 0.5;
    private double variableAlfa = 0.98;
    private double ratioEnfriamiento=0.004;
    private float alfaRecocido=1.0f;
//    static double COSTOOPERACION = 50;
    
    //parametros de metropolis
    
    
    public Solucion crearSolucion(ArrayList<Empleado> empleados, ArrayList<Galleta> arregloGalletas, double alfa){
        
        Solucion sol;
        Grasp algoritmoGrasp = new Grasp();
        sol=algoritmoGrasp.graspConstruccion(empleados,arregloGalletas,1000,alfaRecocido);

        //System.out.println("tamanho en crearSolucion: "+sol.getAsignados().size());
        return sol;
        
    }
    
    public Solucion copiarSolucion2(Solucion sol){
        Solucion nueva = new Solucion();
        nueva.setAsignados( copiaremp(sol.getAsignados()));
        nueva.setGalletas(copiargall(sol.getGalletas()));
        nueva.setFuncionObjetivo(sol.getFuncionObjetivo());
        return nueva;
    }
    
     public Solucion copiarSolucion(Solucion sol){
        Solucion nuevaSol = new Solucion();
        ArrayList<Empleado> listaEmpleados = sol.getAsignados();
        ArrayList<Empleado> nuevaLista = new ArrayList<Empleado>();
        ArrayList<Galleta> listaGalletas = sol.getGalletas();
        ArrayList<Galleta> nuevaGalletas = new ArrayList<Galleta>();
        Empleado aux;
        Galleta auxGalleta;
        
        for (int i=0; i<listaEmpleados.size();i++){
            aux=copiarEmpleado(listaEmpleados.get(i));
            nuevaLista.add(aux);  
        }
        for (int i=0; i<listaGalletas.size();i++){
            auxGalleta=copiarGalleta(listaGalletas.get(i));
            nuevaGalletas.add(auxGalleta);
        }
        
        nuevaSol.setAsignados(nuevaLista);
        nuevaSol.setGalletas(nuevaGalletas);
        nuevaSol.setFuncionObjetivo(sol.getFuncionObjetivo());
        
        return nuevaSol;      
    }
    
    public Empleado copiarEmpleado(Empleado emp){
        Empleado nuevo=new Empleado();
        Galleta nuevoGalleta;
        
        nuevo.setIdempleado(emp.getIdempleado());
        nuevo.setProduccion(emp.getProduccion());
        nuevo.setMermas(emp.getMermas());
        nuevo.setCapacidad(emp.getCapacidad());  
        nuevo.setEficiencia(emp.getEficiencia());
        nuevo.setTipoMaquinaAsignada(emp.getTipoMaquinaAsignada());
        
        nuevoGalleta=copiarGalleta(emp.getGalletaAsignada());
        nuevo.setGalletaAsignada(nuevoGalleta);
        
        return nuevo; 
    }
    
     public ArrayList<Galleta> copiargall(ArrayList<Galleta> array){
       ArrayList<Galleta> arr = new ArrayList() ;
       for(int i =0;i<array.size();i++){
           Galleta b = array.get(i);
        Galleta a = new Galleta(b.getIdgalleta(),b.getTipogalleta(),b.getNumGalletasPedidas());
        arr.add(a);
       }
       return arr;
   }
     
       public ArrayList<Empleado> copiaremp(ArrayList<Empleado> array){
       ArrayList<Empleado> arr = new ArrayList() ;
       for(int i =0;i<array.size();i++){
           Empleado b = array.get(i);
        Empleado a = new Empleado(b.getIdempleado(),b.getProduccion(),b.getMermas());
        arr.add(a);
       }
       return arr;
   }
    
    public Galleta copiarGalleta(Galleta gall){
        Galleta nuevo=new Galleta();
        TipoGalleta nuevoTipo = new TipoGalleta();
        TipoGalleta tipoGalleta = gall.getTipogalleta();
        
        //seteando variables de tipoGalleta
        nuevoTipo.setIdTipo(tipoGalleta.getIdTipo());
        nuevoTipo.setCosto(tipoGalleta.getCosto());
        nuevoTipo.setPrecio(tipoGalleta.getPrecio());
        
        ArrayList<Integer> maquinasProceso = new ArrayList<Integer>(tipoGalleta.getMaquinasProceso());
        ArrayList<Float> porcentajesValor = new ArrayList<Float>(tipoGalleta.getPorcentajesValor());
        nuevoTipo.setMaquinasProceso(maquinasProceso);
        nuevoTipo.setPorcentajesValor(porcentajesValor);
        
        //seteando variables de galleta
        nuevo.setIdgalleta(gall.getIdgalleta());
        nuevo.setNumGalletasPedidas(gall.getNumGalletasPedidas());
        nuevo.setDemandacubierta(gall.getDemandacubierta());
        int[] maq_cub = new int[gall.getDemanda_maq_cubierta().length];
        for(int i=0;i< maq_cub.length;i++) {
            maq_cub[i] = gall.getDemanda_maq_cubierta()[i];
        }
        nuevo.setDemanda_maq_cubierta(maq_cub);
        nuevo.setTipogalleta(tipoGalleta);
        
        return nuevo;  
    }
    
    
    
    
    public Solucion recocido(Solucion solucionInicial,double fObjetivoInicial){
        
        double t=tInicial;
        double fobjetivoAux=0;
        double fobjetivo=fObjetivoInicial;
        Solucion solucion = solucionInicial;
        double metropolis;
        Random randomAux;
        double auxMetro;
        int cambioExitoso=0;
        int randomRuleta;
        Solucion solAux;
        int itera=0;
        int condicionParada=0;
        int i =0;
        int cambioMax;
        while(t>tMinima){
            //System.out.println("T vale:"+t);
            itera++;
            Random r = new Random();
            randomRuleta=r.nextInt(2);
            solAux=copiarSolucion(solucion);
 
            i=i+1;
            cambioMax=0;
            while(cambioExitoso==0){
                cambioMax++;
                if (cambioMax>500) break;
                cambioExitoso = generarVecino(solAux);
            //    System.out.println(" "+i);
                if (cambioExitoso == 1) {
                    solAux.calcularObjetivoTotal(Grasp.COSTOOPERACION);
                    fobjetivoAux = solAux.getFuncionObjetivo();
                
                    cambioExitoso = 0;
                    
               //      System.out.println(" hice cambio "+i);
                    break;
                    
                }                
            }
            
            
            if (fobjetivoAux>0){
                               
                if (fobjetivoAux > fobjetivo) {//CASO: CUANDO FUNCION OBJETIVO DE VECINO ES MAYOR
                    solucion = solAux;
                    fobjetivo = fobjetivoAux;
                    condicionParada=0;
                } else {
                    condicionParada++;
                    if (condicionParada>1000) {
                    System.out.println("CONDICION PARO");
                    break;
                    }
                    metropolis = Math.exp((((fobjetivoAux) - (fobjetivo)) / t));
                    randomAux = new Random();
                    auxMetro=Math.random();
                    if (metropolis > auxMetro) {
                       // System.out.println("REDUCI!");
                        solucion = solAux;
                        fobjetivo = fobjetivoAux;
                    }
                }
            } 
            
            //t=t*variableAlfa;
            t*=1-ratioEnfriamiento;
        }
        solucionInicial=solucion;
        fObjetivoInicial=fobjetivo;
        System.out.println("iteraciones"+itera);
     return solucion;
    }
    
    
    public int generarVecino(Solucion sol){
        
        Random r = new Random();
        int indice1 = r.nextInt(sol.getAsignados().size());
        
        r = new Random();
        int indice2 = r.nextInt(sol.getAsignados().size());
        
        while(indice1==indice2){
            r = new Random();
            indice2 = r.nextInt(sol.getAsignados().size());
        }
        
        Empleado emp1 = sol.getAsignados().get(indice1);
         int maquina1 = emp1.getTipoMaquinaAsignada();
         Galleta gal1 = emp1.getGalletaAsignada();

        Empleado emp2 = sol.getAsignados().get(indice2);
        int maquina2 = emp2.getTipoMaquinaAsignada();
        Galleta gal2 = emp2.getGalletaAsignada();

        int w =0;
        int o=0;
        int posmaq1=0;
        int posmaq2=0;
        
        for(w =0;w< sol.getGalletas().size();w++ ){
          if( gal1.getIdgalleta()== sol.getGalletas().get(w).getIdgalleta()) break; //busco la posicion de la galleta en el arreglo
        }
        
        for(o=0;o< sol.getGalletas().size();o++){
            if(gal2.getIdgalleta()== sol.getGalletas().get(o).getIdgalleta()) break; 
        }
        
        for(posmaq1=0;posmaq1 < sol.getGalletas().get(w).getTipogalleta().getMaquinasProceso().size() ;posmaq1++){
            if(sol.getGalletas().get(w).getTipogalleta().getMaquinasProceso().get(posmaq1)== maquina1 )break;// busco la posicion del tipo de mauqina en el arreglo de maquinas de la galleta
        }
        
        for(posmaq2=0;posmaq2 < sol.getGalletas().get(o).getTipogalleta().getMaquinasProceso().size();posmaq2++){
            if(sol.getGalletas().get(o).getTipogalleta().getMaquinasProceso().get(posmaq2)== maquina2) break;
        }
        int cubierta_tipomaq1 = sol.getGalletas().get(w).getDemanda_maq_cubierta()[posmaq1];//obtengo la demanda cubierta en el tipo de maquina por esa galleta w
       int demanda = sol.getGalletas().get(w).getDemandacubierta();//obtengo la demanda q se debe cubrir
      //     int demanda = sol.getGalletas().get(w).getNumGalletasPedidas();
        int cubierta_tipomaq2 = sol.getGalletas().get(o).getDemanda_maq_cubierta()[posmaq2];
        int demanda2 = sol.getGalletas().get(o).getDemandacubierta();
    //  int demanda2 = sol.getGalletas().get(o).getNumGalletasPedidas();
        
        if(cubierta_tipomaq1 -( emp1.getCapacidad()[maquina1-1] - 
             emp2.getCapacidad()[maquina1-1])>= demanda && cubierta_tipomaq2
              - (emp2.getCapacidad()[maquina2-1]- emp1.getCapacidad()[maquina2-1])>=demanda2)// verifico que en ambos cambios la demanda se siga cubriendo
        {
            emp1.setTipoMaquinaAsignada(maquina2);
            emp1.setGalletaAsignada(gal2);
                        
            emp2.setTipoMaquinaAsignada(maquina1);
            emp2.setGalletaAsignada(gal1);
                         
                 int resta =     ( emp1.getCapacidad()[maquina1-1]-  emp2.getCapacidad()[maquina1-1]);             
            int[]arr= sol.getGalletas().get(w).getDemanda_maq_cubierta();
            arr[posmaq1] = cubierta_tipomaq1 - resta;
            sol.getGalletas().get(w).setDemanda_maq_cubierta(arr);
             
                  
            int resta2 = (emp2.getCapacidad()[maquina2-1]- emp1.getCapacidad()[maquina2-1]);    
            int[] arr2= sol.getGalletas().get(o).getDemanda_maq_cubierta();
            arr2[posmaq2]=cubierta_tipomaq2 - resta2; ;
            sol.getGalletas().get(o).setDemanda_maq_cubierta(arr2);
            
              
            if(maquina1 == 4){
               int[] arrmaquinas = sol.getGalletas().get(w).getDemanda_maq_cubierta();
               int tam = arrmaquinas.length;
               int dem =sol.getGalletas().get(w).getDemanda_maq_cubierta()[tam -1];
               //sol.getGalletas().get(w).calcularDemandacubierta(arrmaquinas);
               sol.getGalletas().get(w).setDemandacubierta(sol.getGalletas().get(w).cubiertoMenor(arrmaquinas));
            }
              
           if(maquina2== 4){
               int[] arrmaquinas2 =sol.getGalletas().get(o).getDemanda_maq_cubierta();
               int tam2 = arrmaquinas2.length;
               int dem2 = sol.getGalletas().get(o).getDemanda_maq_cubierta()[tam2 -1];
               //sol.getGalletas().get(o).calcularDemandacubierta(arrmaquinas2);
               sol.getGalletas().get(o).setDemandacubierta(sol.getGalletas().get(o).cubiertoMenor(arrmaquinas2));
            }
           
           return 1;//se realizo intercambio
        }
//        System.out.println(" intente cambio"+w+" "+o);
       return 0;//no se genero vecino
        
    }
    

    
    public Solucion recocido_run(ArrayList<Empleado> empleados, ArrayList<Galleta> galletas){
         Solucion solInicial;
         solInicial = crearSolucion(empleados, galletas, alfaRecocido);
         solInicial.calcularObjetivoTotal(Grasp.COSTOOPERACION);
         double  fObjetivo=solInicial.getFuncionObjetivo();  
         return recocido(solInicial,fObjetivo);
    
    }
}
